public class MyStringBuilder {
    private char[] value = null;
    private int count;

    //函数假定minCapacity是正值
    //函数必定返回[0,MAX_INT]范围内的值
    private int newCapacity(int minCapacity) {
        if (minCapacity <= 16) return 16;
        int curCapacity;
        if (value == null) curCapacity = 0;
        else curCapacity = value.length;
        int ret = curCapacity;
        while (ret < minCapacity) {
            //curCapacity>1073741822时，乘2加2将超出int范围
            if (curCapacity > 1073741822) return minCapacity;
            ret = ret * 2 + 2;
        }
        return ret;
    }

    public MyStringBuilder() {
        value = new char[16];
        count = 0;
    }

    public MyStringBuilder(String s) {
        if (s == null) {
            value = new char[16];
            count = 0;
        }
        int capacity = newCapacity(s.length());
        value = new char[capacity];
        count = s.length();
        s.getChars(0, s.length(), value, 0);
    }

    public MyStringBuilder(char[] chars) {
        this(String.valueOf(chars));
    }

    public MyStringBuilder append(MyStringBuilder s) {
        if (s == null) return this;
        int totalLen = count + s.length();
        //总长度超限
        if (totalLen < count) return this;
        //新的length没有超过capacity
        if (totalLen <= value.length) {
            System.arraycopy(s.value, 0, value, count, s.count);
        }
        //超过capacity，扩容
        else {
            int newCapacity = newCapacity(totalLen);
            char[] oldValue = value;
            value = new char[newCapacity];
            System.arraycopy(oldValue, 0, value, 0, count);
            System.arraycopy(s.value, 0, value, count, s.count);
        }
        count = totalLen;
        return this;
    }

    public MyStringBuilder append(String s) {
        return this.append(new MyStringBuilder(s));
    }

    public MyStringBuilder append(int i) {
        return this.append(new MyStringBuilder(String.valueOf(i)));
    }

    public char charAt(int index) {
        if (index < 0 || index >= count) return '\0';
        return value[index];
    }

    public MyStringBuilder toLowerCase() {
        for (int i = 0; i <= count; i++) {
            if (value[i] >= 'A' && value[i] <= 'Z') value[i] = (char) (value[i] + 32);
        }
        return this;
    }

    public MyStringBuilder toUpperCase() {
        for (int i = 0; i <= count; i++) {
            if (value[i] >= 'a' && value[i] <= 'z') value[i] = (char) (value[i] - 32);
        }
        return this;
    }

    public MyStringBuilder substring(int begin, int end) {
        //一般地，要求0<=begin<=end<=count
        if (begin < 0 || end > count || begin > end) return null;
        //返回整个串
        if (begin == end) {
            char[] arr = new char[count];
            System.arraycopy(value, 0, arr, 0, count);
            return new MyStringBuilder(arr);
        }
        else {
            int length = end - begin;
            char[] arr = new char[length];
            System.arraycopy(value, begin, arr, 0, length);
            return new MyStringBuilder(arr);
        }
    }

    public MyStringBuilder substring(int begin) {
        return this.substring(begin, count);
    }

    public String toString() {
        char[] arr = new char[count];
        System.arraycopy(value, 0, arr, 0, count);
        return new String(arr);
    }

    public MyStringBuilder insert(int offset, MyStringBuilder s) {
        if (offset < 0 || offset > count) return this;
        if (s == null) return this;
        //等同于追加
        if (offset == count) return this.append(s);
        int totalLen = count + s.count;
        //总长度超限
        if (totalLen < count) return this;
        //新的length没有超过capacity
        //offset必定不等于count
        if (totalLen <= value.length) {
            char[] tmpArr = new char[count - offset];
            System.arraycopy(value, offset, tmpArr, 0, count - offset);
            System.arraycopy(s.value, 0, value, offset, s.count);
            System.arraycopy(tmpArr, 0, value, offset + s.count, tmpArr.length);
        }
        //超过capacity，扩容
        else {
            int newCapacity = newCapacity(totalLen);
            char[] oldValue = value;
            value = new char[newCapacity];
            System.arraycopy(oldValue, 0, value, 0, offset);
            System.arraycopy(s.value, 0, value, offset, s.count);
            System.arraycopy(oldValue, offset, value, offset + s.count, count - offset);
        }
        count = totalLen;
        return this;
    }

    public MyStringBuilder reverse() {
        for (int repeat = 1; repeat <= count / 2; repeat++) {
            int left = repeat - 1, right = count + 1 - repeat - 1;
            char tmp = value[left];
            value[left] = value[right];
            value[right] = tmp;
        }
        return this;
    }

    public int length() {
        return count;
    }

    public void printContentAndLength() {
        char[] tmpArr = new char[count];
        System.arraycopy(value, 0, tmpArr, 0, count);
        System.out.println(tmpArr);
        System.out.println("Length: " + count);
    }

    public static void main(String args[]) {
        MyStringBuilder empty = new MyStringBuilder();
        //<empty> 0
        empty.printContentAndLength();
        MyStringBuilder str = new MyStringBuilder("Welcome to Hoenn.");
        //Welcome to Hoenn. 17
        str.printContentAndLength();
        MyStringBuilder chars = new MyStringBuilder("Welcome to Unova.".toCharArray());
        //Welcome to Unova. 17
        chars.printContentAndLength();
        str.insert(str.length() - 1, new MyStringBuilder(" and Unova"));
        //Welcome to Hoenn and Unova. 27
        str.printContentAndLength();
        empty.append("Hello. ");
        //"Hello. " 7
        empty.printContentAndLength();
        empty.append(str);
        //Hello. Welcome to Hoenn and Unova. 34
        empty.printContentAndLength();
        empty.append(123);
        //Hello. Welcome to Hoenn and Unova.123 37
        empty.printContentAndLength();
        chars.toLowerCase();
        //welcome to unova. 17
        chars.printContentAndLength();
        chars.toUpperCase();
        //WELCOME TO UNOVA. 17
        chars.printContentAndLength();
        MyStringBuilder tmp=chars.substring(11,16);
        //WELCOME TO UNOVA. 17
        chars.printContentAndLength();
        //UNOVA 5
        tmp.printContentAndLength();
        tmp.reverse();
        //AVONU 5
        tmp.printContentAndLength();
        tmp=chars.substring(11);
        //UNOVA. 6
        tmp.printContentAndLength();
        //WELCOME TO UNOVA.
        System.out.println(chars.toString());
    }

    //为实现类似String.getChars功能而写的函数
    //但好像用处并不大
//    public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
//        //特殊参数处理
//        //一般地，要求0<=srcBegin<srcBegin+1<=srcEnd<=value.length
//        if (srcBegin < 0 || srcEnd < 0 || srcBegin > value.length ||
//                srcEnd > value.length || dstBegin < 0 || dstBegin >= dst.length) return;
//        if (srcBegin > srcEnd) return;
//        //至此，0<=srcBegin<=srcEnd<=value.length，且0<=dstBegin<dst.length
//        //需复制字段的长度
//        int length;
//        if (srcBegin == srcEnd) length = value.length;
//        else length = srcEnd - srcBegin;
//        length = Math.min(length, dst.length - dstBegin);
//        System.arraycopy(value, 0, dst, dstBegin, length);
//    }
}
